package com.easpeed.elevator.udp;

import android.content.Context;
import android.os.Process;
import android.util.Log;
import com.bigyu.utils.Logger;

import com.easpeed.comon.consts.CustomSetting;
import com.easpeed.elevator.event.SendOrderEvent;
import com.easpeed.elevator.utils.ByteUtil;
import com.easpeed.elevator.utils.FirDataProcessor;

import org.greenrobot.eventbus.EventBus;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Arrays;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.LinkedBlockingQueue;

public class UdpTool {

    private static UdpTool instance;
    private String TAG = "UdpTool";
    DatagramSocket mSocket;
    Context context;

    boolean isFriProcess; //是否开启滤波
    LinkedBlockingQueue<DatagramPacket> dataQueue = new LinkedBlockingQueue<>();
    LinkedBlockingQueue<float[]> dvsQueue = new LinkedBlockingQueue<>();

    int ByteArrayPoolSize = 10000;

    FirDataProcessor processor;

    public static synchronized UdpTool getInstance(Context context) {
        if (instance == null) {
            instance = new UdpTool(context.getApplicationContext());
        }

        return instance;
    }


    public UdpTool(Context context) {
        this.context = context;
        startLoggingTimer();

        processor = new FirDataProcessor(context);
        startPipeline();

        try {
            this.receiveMessage();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void setModel(String model){
        this.processor.setModel(model);
    }

    public String getModel(){
        return this.processor.getModel();
    }

    public void EnableFriFilters() {
        this.isFriProcess = true;
    }

    public void DisableFriFilters() {
        this.isFriProcess = false;
    }

    /**
     * 发送信息
     *
     * @param msg 信息内容
     * @param
     */
    public void sendMessage(String msg) {
        // 需要开线程来发数据
        new Thread(new Runnable() {
            @Override
            public void run() {
                if (mSocket == null) {
                    try {
                        // 这个是本机的端口号
                        mSocket = new DatagramSocket(6003);

                    } catch (SocketException e) {
                        e.printStackTrace();
                    }
                }
                // 将字符串转换成字节流，因为底层的传输都是字节传输
                byte[] data = ByteUtil.hexStr2bytes(msg);
                try {
                    // 对方ip和端口
                    DatagramPacket pack = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.137.2"), 6002);
                    mSocket.send(pack);
                    Logger.d(TAG, "发送成功！" + ByteUtil.bytes2HexStr(data));

                } catch (IOException e) {
                    Logger.d(TAG, "发送失败！");
                    e.printStackTrace();
                }
            }
        }).start();
    }

    public void receiveMessage() throws Exception {

        byte[] expectedHeader = new byte[]{(byte) 0x5A, (byte) 0xA5, (byte) 0x55, (byte) 0xAA, (byte) 0xAA, (byte) 0x55, (byte) 0x00, (byte) 0x03};
        Thread thread = new Thread(() -> {
            Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO);
            try {
                if (mSocket == null) {
                    mSocket = new DatagramSocket(6001);
                    mSocket.setReceiveBufferSize(1048576);//16777216//4194304//1048576//262144
                }

                ByteArrayPool bap = new ByteArrayPool(ByteArrayPoolSize, 1040);
                while (true) {
                    byte[] data = bap.acquire();
                    DatagramPacket pack2 = new DatagramPacket(data, data.length);

                    try {
                        mSocket.receive(pack2);
                    } catch (IOException e) {
                        continue;
                    }
                    if (Arrays.equals(Arrays.copyOf(pack2.getData(), expectedHeader.length), expectedHeader)) {
                        logCount++;
                        dataQueue.put(pack2);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                Logger.e(TAG,e.toString());
            }
        });
//        thread.setPriority(Thread.MAX_PRIORITY);
        thread.start();
    }

    public void startPipeline() {
        Thread t1 = new Thread(this::transferDVS);
//        t1.setPriority(Thread.MAX_PRIORITY);
        t1.start();

//        Thread t2 = new Thread(this::collectDVS);
//        t2.setPriority(Thread.MAX_PRIORITY);
//        t2.start();
    }

    // 处理数据的线程
    public void transferDVS() {
        Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO);
//        FloatArrayPool fap = new FloatArrayPool(FloatArrayPoolSize, 20000);
        float[] dvsList = new float[CustomSetting.getDvsPointNum()];//fap.acquire();
        int currentSize = 0;


        while (true) {
            try {
                DatagramPacket packet = dataQueue.take();
                byte[] data = packet.getData();
                int length = packet.getLength();

//                if (Arrays.equals(Arrays.copyOf(data, expectedHeader.length), expectedHeader)) {
//                if ( ByteUtil.bytes2HexStr(packet.getData(), 0, 8).equals("5AA555AAAA550003")){
                logCount2++;
                // 直接处理数据而不是创建新的数组
                for (int i = 16; i < length; i += 2) {
                    if (currentSize < dvsList.length) {
                        float band = hexToInt16Signed(data[i], data[i + 1]);
//                            if (band>20 && currentSize > 11000){
//                                Logger.e("sheng5","band :"+band+" ,index:"+currentSize);
//                            }
                        dvsList[currentSize] = band;
                        currentSize++;
                    }
                }

                // 提取 ordertype
                String ordertype = ByteUtil.bytes2HexStr(data, 10, 2);
//                Logger.e("FirFilters", "张量解析数据，ordertype="+ordertype +"  currentSize="+currentSize);


                if ("1100".equals(ordertype)) {
                    if (currentSize == CustomSetting.getDvsPointNum()) {
                        if (isFriProcess) {
                            logCount3++;
                            processor.processData(dvsList);
                        } else {
                            EventBus.getDefault().post(new SendOrderEvent(dvsList,1,0));
                        }
                    }
//                    dvsList = fap.acquire();
                    currentSize = 0; // 重置当前大小
                } else if (currentSize >= CustomSetting.getDvsPointNum()) {
//                    dvsList = fap.acquire();
                    currentSize = 0; // 丢弃之前的数据
                }
//                } else {
//                    // 记录无效数据包的日志
//                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

    public void collectDVS() {
        while (true) {
            try {
                float[] dvs = dvsQueue.take();
                logCount3++;

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static int hexToInt16Signed(byte b1,byte b2) {
        // 将十六进制字符串转换为无符号的整数
        int num = uint16ToInt(b1, b2);
        // 检查最高位（符号位）
        if ((num & 0x8000) != 0) {
            // 如果最高位是1，则是有符号整数的负数
            // 使用位运算将其转换为正数（取反加一）
            num = -(0xFFFF - num + 1);
        }

        // 返回绝对值（在这个情况下，因为我们已经处理了负数，所以直接返回即可）
        return Math.abs(num);
    }


    public static int uint16ToInt(byte b1,byte b2) {
        return (b1 & 0xFF) << 8 | (b2 & 0xFF);
    }

    int logCount = 0; // 计数器
    int logCount2 = 0; // 计数器
    int logCount3 = 0; // 计数器
    Timer timer = new Timer(); // 定时器

    // 启动计时器，统计下一秒内的日志数量
    public void startLoggingTimer() {
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                Logger.d(TAG, "Logs in last second: " + logCount + ",logs2:" + logCount2 + ",logs3:" + logCount3);
                logCount = 0; // 重置计数
                logCount2 = 0;
                logCount3 = 0;
            }
        }, 0, 1000); // 每秒打印一次
    }


    /**
     * 接收消息的函数
     */
//    public void receiveMessage() throws Exception {
//        // 创建线程，同理，接收信息也要放在线程里面接收
//        new Thread(new Runnable() {
//            public void run() {
//                try {
//                    if (mSocket == null) {
//                        mSocket = new DatagramSocket(6001);
//                    }
//                    while (true) {
//                        // 创建一个空的字节数组
//                        byte[] data = new byte[1040];
//                        // 将字节数组和数组的长度传进DatagramPacket 创建的对象里面
//                        DatagramPacket pack2 = new DatagramPacket(data, data.length);
////                        Log.v("s", "pack2"+pack2.toString());
////                        Log.v("s", "开始 接收");
//                        try {
//                            // socket对象接收pack包，程序启动的时候，socket会一直处于阻塞状态，直到有信息传输进来
//                            mSocket.receive(pack2);
//                        } catch (IOException e) {
//                            e.printStackTrace();
//                        }
//                        // 获取发送数据的IP地址
//                        String ip = pack2.getAddress().getHostAddress();
//                        // 获取发送数据端的端口号
//                        int port = pack2.getPort();
////                        Logger.e("oye", "开始 接收"+ip+"---"+port);
//                        // 开启接收端口后会持续接收数据，只有页面可见的时候才将收到的数据写入
//                        String hexStr = ByteUtil.bytes2HexStr(pack2.getData(), 0, pack2.getLength());
////                        Logger.e("oye", "开始 接收"+hexStr+pack2.getLength());
//                        if ( ByteUtil.bytes2HexStr(pack2.getData(), 0, 8).equals("5AA555AAAA550003")){
//                            EventBus.getDefault().post(new GetUdpMessageEvent(pack2.getData(),pack2.getLength()));
//                        }
//
//                    }
//                } catch (Exception e) {
//                    e.printStackTrace();
//                }
//            }
//        }).start();
//    }

    /**
     * 关闭通信
     */
    public void closeSocket() {
        if (mSocket != null) {
            mSocket.close();
            mSocket = null;
        }
    }
}
